package com.findme.securitydb.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.findme.securitydb.filter.JwtFilter;
import com.findme.securitydb.filter.JwtLoginFilter;
import com.findme.securitydb.service.UserService;
import com.findme.securitydb.utils.returnTool.ResTool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.authentication.*;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author 江南一点雨
 * @Site www.javaboy.org 2019-08-11 17:16
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Resource
    private ObjectMapper objectMapper;

    @Override
    @Bean
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Autowired
    UserService userService;
    @Autowired
    MyFilter myFilter;
    @Autowired
    MyAccessDecisionManager myAccessDecisionManager;

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 此处去调用数据库的或者采用静态数据
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
        // 静态的写法
//        auth.inMemoryAuthentication()
//                .withUser("javaboy").password("$2a$10$zD1IhF0k2zaWY1ceEt9MkOiDJC7NQMgNEx38Eal1txWArGqGWiLza").roles("admin")
//                .and()
//                .withUser("user").password("$2a$10$zD1IhF0k2zaWY1ceEt9MkOiDJC7NQMgNEx38Eal1txWArGqGWiLza").roles("user");

    }


    @Bean
    RoleHierarchy roleHierarchy() {
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        String hierarchy = "dba > admin \n admin > user";
        roleHierarchy.setHierarchy(hierarchy);
        return roleHierarchy;
    }
//    @Bean
//    @Override
//    protected UserDetailsService userDetailsService() {
//        return super.userDetailsService();
//    }


//    @Override
//    protected void configure(HttpSecurity http) throws Exception {
//        //对于不同的路径要不同的角色 静态配置
//        http.authorizeRequests()
//                .antMatchers("/dba/**").hasRole("dba")
//                .antMatchers("/admin/**").hasRole("admin")
//                .antMatchers("/user/**").hasRole("user")
//                .anyRequest().authenticated()
//                .and()
//                .formLogin()
//                .permitAll()
//                .and()
//                .csrf().disable();
//    }


    /**
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
                        o.setAccessDecisionManager(myAccessDecisionManager);
                        o.setSecurityMetadataSource(myFilter);
                        return o;
                    }
                })
                .and()
                .formLogin()
                .permitAll()
                .and()
                .csrf().disable();
    }
//    @Override
//    protected void configure(HttpSecurity http) throws Exception {
//        http.authorizeRequests()
//                .antMatchers(HttpMethod.POST, "/login")
//                .permitAll()
//
//                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
//                    @Override
//                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
//                        o.setAccessDecisionManager(myAccessDecisionManager);
//                        o.setSecurityMetadataSource(myFilter);
//                        return o;
//                    }
//                })
//                .and()
//                .formLogin()
////                .loginProcessingUrl("/login")
////                .loginPage("/login")
////                .usernameParameter("uname")
////                .passwordParameter("passwd")
//                .successHandler(new AuthenticationSuccessHandler() {
//                    @Override
//                    public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
//                        resp.setContentType("application/json;charset=utf-8");
//                        PrintWriter out = resp.getWriter();
//                        Map<String, Object> map = new HashMap<>();
//                        map.put("status", 200);
//                        map.put("msg", authentication.getPrincipal());
//                        out.write(new ObjectMapper().writeValueAsString(map));
//                        out.flush();
//                        out.close();
//                    }
//                })
//                .failureHandler(new AuthenticationFailureHandler() {
//                    @Override
//                    public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException {
//                        resp.setContentType("application/json;charset=utf-8");
//                        PrintWriter out = resp.getWriter();
//                        Map<String, Object> map = new HashMap<>();
//                        map.put("status", 401);
//                        if (e instanceof LockedException) {
//                            map.put("msg", "账户被锁定，登录失败!");
//                        } else if (e instanceof BadCredentialsException) {
//                            map.put("msg", "用户名或密码输入错误，登录失败!");
//                        } else if (e instanceof DisabledException) {
//                            map.put("msg", "账户被禁用，登录失败!");
//                        } else if (e instanceof AccountExpiredException) {
//                            map.put("msg", "账户过期，登录失败!");
//                        } else if (e instanceof CredentialsExpiredException) {
//                            map.put("msg", "密码过期，登录失败!");
//                        } else {
//                            map.put("msg", "登录失败!");
//                        }
//                        out.write(new ObjectMapper().writeValueAsString(map));
//                        out.flush();
//                        out.close();
//                    }
//                })
//                .permitAll()
//                .and()
//                .logout()
//                .logoutUrl("/logout")
//                .logoutSuccessHandler(new LogoutSuccessHandler() {
//                    @Override
//                    public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
//                        resp.setContentType("application/json;charset=utf-8");
//                        PrintWriter out = resp.getWriter();
//                        Map<String, Object> map = new HashMap<>();
//                        map.put("status", 200);
//                        map.put("msg", "注销登录成功!");
//                        out.write(new ObjectMapper().writeValueAsString(map));
//                        out.flush();
//                        out.close();
//                    }
//                })
//                .and()
//                // 加上这两个过滤器 参数，登录地址，登录信息
//                .addFilterBefore(new JwtLoginFilter("/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class)
//                .addFilterBefore(new JwtFilter(), UsernamePasswordAuthenticationFilter.class)
//                .csrf().disable();
//
////        http.addFilterAt(myAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
//
////        /**
////         * 权限不足处理
////         */
//        http.exceptionHandling().accessDeniedHandler(new AccessDeniedHandler() {
//            @Override
//            public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException
//                    e) throws IOException {
//
//                httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
//
//                Map<String, Object> failureMap = new HashMap<>();
//                ResTool.build().code(405).msg("权限不足!");
//                failureMap.put("code", "405");
//                failureMap.put("msg", "权限不足！");
//
//                httpServletResponse.getWriter().println(objectMapper.writeValueAsString(failureMap));
////                httpServletResponse.getWriter().println(ResTool);
//
//            }
//        });
//        // 不起作用
////        /**
////         * 未登陆处理
////         */
////        http.exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() {
////            @Override
////            public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
////
////
////                httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
////
////                Map<String, Object> failureMap = new HashMap<>();
////                failureMap.put("code", 401);
////                failureMap.put("msg", "请先登录！");
////
////                httpServletResponse.getWriter().println(objectMapper.writeValueAsString(failureMap));
////
////            }
////        });
////    }
//}
//    @Bean
//    MyAuthenticationFilter myAuthenticationFilter() throws Exception {
//        MyAuthenticationFilter filter = new MyAuthenticationFilter();
//
//        filter.setAuthenticationManager(authenticationManagerBean());
//        return filter;
//    }
}
